<?php
/*
 *  Copyright (C) 2009 Mauro Rocco "fireantology@gmail.com"
 *
 *  This file is part of PTwix.
 *
 *  PTwix is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  PTwix is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with PTwix.  If not, see <http://www.gnu.org/licenses/>.
 */


/**
 * Implements a Twitter grabber
 */
class PtwiX {
    public  $twitter_base  = 'http://twitter.com/statuses/';
    private $twitter_base_search  = 'http://search.twitter.com/search.json?';
    private $preurl_user="http://twitter.com/";
    private $preurl_tag="http://search.twitter.com/search?q=";
    private $instance_name;
    private $username;
    private $password;
    private $path;
    private $theme;
    private $timeline;
    private $cache_folder;
    private $width;
    private $height;
    private $async_filename;
    private $useCurl=true;
    private $string_to_search="q=ptwix";
    private $showFollowMe=true;
    private $searchTitle="";

    public static $USER_TIMELINE=0;
    public static $FRIENDS_TIMELINE=1;
    public static $SEARCH=2;

    /**
     * Create a Twitter grabber
     * @param $instance_name
     * @param $username Twitter username
     * @param $password Twitter password
     * @param $path Url path of ptwix folder (http://www.mysite.com/ptwix)
     * @param $cache_folder Absolute path of cache folder (/var/www/mysite/ptwix/cache)
     * @param $timeline The type of timeline to show (User timeline or Friends timeline) use static variable (Ptwix::USER_TIMELINE)
     * @param $theme Theme folder name
     */

    public function  __construct($instance_name,$username, $password, $path, $cache_folder, $timeline=1, $theme="gray-blue") {

        if(!$this->validateParameter($theme)) die("The theme name must contains only [a-zA-Z0-9_-] ");
        if(!$this->validateParameter($instance_name)) die("The instance name must contains only [a-zA-Z0-9_-] ");
        $this->username=$username;
        $this->password=$password;
        $this->path=$path;
        $this->theme=$theme;
        $this->timeline=$timeline;
        $this->instance_name=$instance_name;
        $this->cache_folder=$cache_folder;
        $this->width=400;
        $this->height=265;
        $this->async_filename="PtwiX_reader.php";
    }

    /**
     * Set dimension of PtwiX box
     * @param $width box width
     * @param $height box height
     */

    public function setDimension($width, $height) {
        $this->width=$width;
        $this->height=$height;
    }

    /**
     * Activate or Deactivate curl request
     * @param $boolean true for Using curl function
     */

    public function useCurl($boolean) {
        $this->useCurl=$boolean;
    }

    /**
     * Hide the follow me button
     */

    public function hideFollowMe() {
        $this->showFollowMe=false;
    }


    /**
     * Setting a string for twitter search
     * @param $string the search string (q=twitter&rpp=20)
     */

    public function setSearchString($string) {
        $this->string_to_search=$string;
    }

    /**
     * Setting a title for the search box
     * @param $string the title
     */

    public function setSearchTitle($string) {
        $this->searchTitle=$string;
    }

    /**
     * Set asichronous file
     * @param $name asynchronous file name
     */

    public function setAsyncFileName($name) {
        $this->async_filename=$name;
    }

    private function validateParameter($string) {
        return preg_match("/^[a-zA-Z0-9_-]+$/",$string);
    }

    /**
     * Print html code for css include
     */

    public function printCssRef() {
        echo '<link href="'.$this->path.'themes/'.$this->theme.'/PtwiX.css" rel="stylesheet" type="text/css" />';
    }

    private function parseText($text) {
        $text.=" ";
        $text=preg_replace("/http:\/\/([^ ]+) /", "<a href=\"http://$1\" target=\"_blank\">http://$1</a> ", $text);
        $text=preg_replace("/@([a-zA-z0-9_]+)/", "@<a href=\"".$this->preurl_user."$1\" target=\"_blank\">$1</a> ", $text);
        $text=preg_replace("/#([a-zA-z0-9_]+)/", "#<a href=\"".$this->preurl_tag."$1\" target=\"_blank\">$1</a> ", $text);
        return $text;
    }


    private function dateFormatting($date) {
        $temp=strtotime($date);
        $date=date("d M Y H:i", $temp);
        return $date;
    }

    /**
     * Get Twitter post as html
     * @param $timeline
     * @return string post html code
     */

    public function  getData($timeline) {
        $messages="";
        $response=$this->buildMessagesArray($timeline);
        foreach ($response as $status) {
            $messages.= '<div id="item_Ptwix">';

            $messages.= '<div id="text_Ptwix"><img src="'.$status['profile_image_url'].'"><a href="'.$this->preurl_user.$status['user_screen_name'].'" target="_blank"><b>' . $status['user_screen_name'] . '</b></a>: '.$this->parseText($status['text']);
            $messages.= '<div id="date_Ptwix"><em>on ' . $this->dateFormatting($status['created_at']);
            if($status['in_reply_to_screen_name']!="")
                $messages.= ' in reply to <a href="'.$this->preurl_user.$status['in_reply_to_screen_name'].'" target="_blank">'.$status['in_reply_to_screen_name'].'</a>';
            $messages.="</em></div><div style=\"clear: both; display: block;\"> </div></div><div style=\"clear: both; display: block;\"> </div></div>";
        }

        return $messages;
    }

    private function buildMessagesArray($timeline) {
        $messages_array=array();
        if($timeline==self::$SEARCH) {
            $json_object=json_decode(file_get_contents($this->readFile($timeline)));
            foreach ($json_object->{'results'} as $message) {
                $temp=array();
                $temp['profile_image_url']=$message->{'profile_image_url'};
                $temp['user_screen_name']=$message->{'from_user'};
                $temp['text']=$message->{'text'};
                $temp['created_at']=$message->{'created_at'};
                $temp['in_reply_to_screen_name']=$message->{'to_user'};
                $messages_array[]=$temp;
            }
        }
        else {
            $xml_object=$XML=simplexml_load_file($this->readFile($timeline));
            foreach ($xml_object as $message) {
                $temp=array();
                $temp['profile_image_url']=$message->user->profile_image_url;
                $temp['user_screen_name']=$message->user->screen_name;
                $temp['text']=$message->text;
                $temp['created_at']=$message->created_at;
                $temp['in_reply_to_screen_name']=$message->in_reply_to_screen_name;
                $messages_array[]=$temp;
            }
        }
        return $messages_array;
    }

    /**
     * Print html/javascript PtiwX box
     */

    public function printBox() {
        echo "<script type=\"text/Javascript\">";
        echo $this->returnJs();
        echo "</script>";
        echo "<div id=\"PtwiX_".$this->theme."\" style=\"width: ".$this->width."px;\">";
        echo "	<div id=\"top_Ptwix\">
            <div id=\"center_Ptwix\">
            <div id=\"left_Ptwix\"><a href=\"http://ptwix.toforge.com\" target=\"_blank\"><img src=\"".$this->path."themes/".$this->theme."/images/top_left.png\" border=\"0\"></a></div>
            <div id=\"text_Ptwix\">";
        if($this->showFollowMe && $this->timeline!=self::$SEARCH) {
            echo "<a href=\"".$this->preurl_user.$this->username."\"><img align=\"absmiddle\" src=\"".$this->path."themes/".$this->theme."/images/followme.png\" border=\"0\"></a>&nbsp; <a href=\"".$this->preurl_user.$this->username."\">Follow me on twitter </a>&nbsp;&nbsp;";
        }
        if($this->timeline==self::$SEARCH) {
            echo "<b>".$this->searchTitle."</b>&nbsp;&nbsp;";
        }
        echo "<a href=\"javascript:void(0)\" onclick=\"".$this->instance_name."PtwiXdoLoad()\"><img align=\"absmiddle\" src=\"".$this->path."themes/".$this->theme."/images/refresh.png\" border=\"0\"></a>&nbsp;<a href=\"javascript:void(0)\" onclick=\"".$this->instance_name."PtwiXdoLoad()\">Update</a></div>
            <div id=\"right_Ptwix\"><img src=\"".$this->path."themes/".$this->theme."/images/top_right.png\" border=\"0\"></div>
            </div>
            </div>
            <div id=\"content_Ptwix\">
            <div id=\"".$this->instance_name."PtwiXOverFlow\" class=\"PtwiXOverFlow\" style=\"height: ".$this->height."px;\">";
        echo $this->getData($this->timeline);
        echo "</div></div><div id=\"bottom_Ptwix\"><div id=\"center_Ptwix\">
            <div id=\"left_Ptwix\"><img src=\"".$this->path."themes/".$this->theme."/images/bottom_left.png\" border=\"0\"></div>
            <div id=\"right_Ptwix\"><img src=\"".$this->path."themes/".$this->theme."/images/bottom_right.png\" border=\"0\"></div>
            </div></div><div style=\"display:block; clear: both;\"> </div>";
        echo "</div>";
    }



    /**
     * Get JS code for PtwiX interface handler
     */

    function returnJS() {
        $js=' function '.$this->instance_name.'PtwiXCreateXmlHttpReq(handler) {

        var xmlhttp = null;
        try {
            xmlhttp = new XMLHttpRequest();
        } catch(e) {
            try {
                xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
            } catch(e) {
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
        }
        '.$this->instance_name.'PtwiXonLoading();
        xmlhttp.onreadystatechange = handler;
        return xmlhttp;
    }



    function '.$this->instance_name.'PtwiXHandler()
    {
        if (myRequest.readyState == 4 && myRequest.status == 200)
        {
                '.$this->instance_name.'PtwiXprint(myRequest.responseText);

        }
    else if(myRequest.readyState == 4 && myRequest.status == 404){
        '.$this->instance_name.'PtwiXprint("Pagina not found, check configuration file");
    }
    else if(myRequest.readyState == 4){
        '.$this->instance_name.'PtwiXprint("Server Error");
    }

    }

    function '.$this->instance_name.'PtwiXprint(content){
    document.getElementById(\''.$this->instance_name.'PtwiXOverFlow\').innerHTML=content;
    }

    function '.$this->instance_name.'PtwiXonLoading(){
    document.getElementById(\''.$this->instance_name.'PtwiXOverFlow\').innerHTML=\'<img style="margin-top: '.(($this->height/2)-40).'px;" id="LoadingImage_PtwiX" src="'.$this->path.'themes/'.$this->theme.'/images/ptwix_loading.gif" align="center">\';
    }

    function '.$this->instance_name.'PtwiXdoLoad()
    {
        myRequest = '.$this->instance_name.'PtwiXCreateXmlHttpReq('.$this->instance_name.'PtwiXHandler);
        myRequest.open("POST","'.$this->path.'as/'.$this->async_filename.'");
        myRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
        myRequest.send("&theme='.$this->theme.'&timeline='.$this->timeline.'&instance_name='.$this->instance_name.'&search_string='.$this->string_to_search.'");


    }';
        return $js;
    }

    private function readFile($timeline) {
        $file_date=$this->cache_folder.$this->instance_name."date.dat";
        $fd = @fopen($file_date, 'r');
        if(!$fd) $this->writeFile($timeline);
        else {
            $date = fread($fd, filesize($file_date));
            fclose($fd);
            if(time()-$date>60)  $this->writeFile($timeline);
        }
        $cache_file=$this->cache_folder.$this->instance_name."cache.xml";
        return $cache_file;
    }

    private function writeFile($timeline) {
        $messages=$this->requestStatuses($timeline);

        if($timeline!=self::$SEARCH) {
            $XML=new SimpleXMLElement($messages);
            if($XML[0]->error) {
                $file_log=fopen($this->cache_folder.$this->instance_name."Error.log", "w");
                fwrite($file_log, date("Y-m-d H:i:s")."\n".$messages);
                fclose($file_log);
            }
            else {
                $file=fopen($this->cache_folder.$this->instance_name."cache.xml", "w");
                fwrite($file, $messages);
                fclose($file);
            }
        }
        else {
            $file=fopen($this->cache_folder.$this->instance_name."cache.xml", "w");
            fwrite($file, $messages);
            fclose($file);
        }
        $file_date=fopen($this->cache_folder.$this->instance_name."date.dat", "w");
        fwrite($file_date, time());
        fclose($file_date);
        return 1;
    }

    private function requestStatuses($timeline) {
        $string_timeline="";
        $xml="";
        if($timeline==self::$FRIENDS_TIMELINE) { $string_timeline = $this -> twitter_base . "friends_timeline/" . $this -> username . '.xml?count=20'; }
        else if($timeline==self::$USER_TIMELINE) { $string_timeline = $this -> twitter_base . "user_timeline/" . $this -> username . '.xml?count=20';  }
            else if($timeline==self::$SEARCH) { $string_timeline = $this -> twitter_base_search . $this->string_to_search;  }
        if($this->useCurl) {
            $handler_curl = curl_init();
            curl_setopt($handler_curl, CURLOPT_URL, $string_timeline);
            curl_setopt($handler_curl, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($handler_curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
            curl_setopt($handler_curl, CURLOPT_USERPWD, $this->username.':'.$this->password);
            $xml= curl_exec($handler_curl);
            curl_close($handler_curl);
            unset($handler_curl);
        }
        else {
            $xml = file_get_contents($string_timeline);
        }
        return $xml;
    }

}
?>